/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.taglib.core.logic;

import com.blandware.atleap.webapp.taglib.core.ParamParent;
import com.blandware.atleap.webapp.util.core.RequestUtil;
import com.blandware.atleap.webapp.util.core.WebappUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.taglib.html.Constants;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>Performs redirect to the URL, generated from given params. Generation is
 * made in process called ' URL rewriting'. For its definition, see
 * {@link com.blandware.atleap.webapp.taglib.core.html.RewriteUrlTag}.
 * </p>
 * <p>
 * Allowed attributes are:
 * <ul>
 * <li>
 * <b>action</b> - name of Action to construct URL for
 * </li>
 * <li>
 * <b>forward</b> - name of Global Action forward to construct URL for
 * </li>
 * <li>
 * <b>href</b> - URL to rewrite
 * </li>
 * <li>
 * <b>anchor</b> - the anchor to be added to the end of the generated hyperlink
 * </li>
 * <li>
 * <b>transaction</b> - whether to include transaction token (if any) in the
 * URL. May be "false" or "true", default is "false"
 * </li>
 * <li>
 * <b>addLocaleSuffix</b> - whether to add locale suffix before extension. May
 * be "false" or "true", default is "true".
 * </li>
 * </ul>
 * </p>
 * <p>
 * This tag may also accept parameters through &lt;atleap:param&gt; tag. They
 * are added to resulting URL.
 * </p>
 * <p>
 * Only one of <b>action</b>, <b>forward</b> or <b>href</b> must be
 * specified.
 * </p>
 * <p>
 * Here's an example:
 * <pre>
 * &lt;atleap:redirect action="login"&gt;
 *     &lt;atleap:param name="error" value="true"&gt;
 * &lt;/atleap:redirect&gt;
 * </pre>
 * This code will redirect user to page corresponding to 'login' action,
 * request will contain a parameter with name 'error' and value 'true'.
 * </p>
 * <p><a href="RedirectTag.java.html"><i>View Source</i></a></p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.6 $ $Date: 2006/08/03 10:08:24 $
 * @see com.blandware.atleap.webapp.taglib.core.ParamTag
 * @jsp.tag name="redirect"
 * body-content="scriptless"
 */
public class RedirectTag extends SimpleTagSupport implements ParamParent {

	protected transient final Log log = LogFactory.getLog(RedirectTag.class);

	/**
	 * Name of Action to construct URL for
	 */
	protected String action;

	/**
	 * Name of Global Action forward to construct URL for
	 */
	protected String forward;

	/**
	 * HREF to rewrite
	 */
	protected String href;

	/**
	 * The anchor to be added to the end of the generated hyperlink.
	 */
	protected String anchor;

	/**
	 * Include transaction token (if any) in the URL?
	 */
	protected Boolean transaction = Boolean.FALSE;

	/**
	 * Whether or not to add locale suffix before extension
	 */
	protected Boolean addLocaleSuffix = Boolean.TRUE;

	/**
	 * Local parameters
	 */
	protected Map parameters = new HashMap();

	/**
     * Returns name of Action to construct URL for
     *
	 * @return name of Action
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Name of Action to construct URL for"
	 */
	public String getAction() {
		return action;
	}

    /**
     * Sets name of Action to construct URL for
     *
     * @param action name of Action to set
     */
	public void setAction(String action) {
		this.action = action;
	}

	/**
     * Returns name of Global Action forward to construct URL for
     *
	 * @return name of Global Action forward
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Name of Global Action forward to construct URL for"
	 */
	public String getForward() {
		return forward;
	}

    /**
     * Sets name of Global Action forward to construct URL for
     *
     * @param forward name of Global Action forward
     */
	public void setForward(String forward) {
		this.forward = forward;
	}

	/**
     * Returns href
     *
	 * @return href
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="HREF to rewrite"
	 */
	public String getHref() {
		return href;
	}

    /**
     * Sets href
     *
     * @param href href to set
     */
	public void setHref(String href) {
		this.href = href;
	}

	/**
     * Returns anchor that will be added to link
     *
     * @return anchor
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Anchor to append to the name of generated hyperlink"
	 */
	public String getAnchor() {
		return anchor;
	}

    /**
     * Sets anchor that will be added to link
     *
     * @param anchor anchor to set
     */
	public void setAnchor(String anchor) {
		this.anchor = anchor;
	}

	/**
     * Returns whether or not to include transaction token in the URL
     *
     * @return whether to include transaction token in the URL
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.String"
	 * description="Whether or not to include transaction token in the URL"
	 */
	public Boolean getTransaction() {
		return transaction;
	}

    /**
     * Sets whether or not to include transaction token in the URL
     *
     * @param transaction whether to include transaction token in the URL
     */
	public void setTransaction(Boolean transaction) {
		this.transaction = transaction;
	}

	/**
     * Returns whether or not to include locale suffix in the URL
     *
     * @return whether to include locale suffix in the URL
	 * @jsp.attribute required="false"
	 * rtexprvalue="true"
	 * type="java.lang.Boolean"
	 * description="Whether or not to add locale suffix before extension"
	 */
	public Boolean getAddLocaleSuffix() {
		return addLocaleSuffix;
	}

    /**
     * Sets whether or not to include locale suffix in the URL
     *
     * @param addLocaleSuffix whether to include locale suffix in the URL
     */
	public void setAddLocaleSuffix(Boolean addLocaleSuffix) {
		this.addLocaleSuffix = addLocaleSuffix;
	}

    /**
     * Processes the tag
     *
     * @throws JspException
     * @throws IOException
     */
	public void doTag() throws JspException, IOException {

		PageContext pageContext = (PageContext) getJspContext();
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
		HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();

		if ( transaction == null ) {
			transaction = Boolean.FALSE;
		}

		if ( addLocaleSuffix == null ) {
			addLocaleSuffix = Boolean.TRUE;
		}

		// invoke body content
		JspFragment body = getJspBody();
		if ( body != null ) {
			body.invoke(null);
		}

		// calculate transaction token if requested
		if ( transaction.booleanValue() ) {
			HttpSession session = pageContext.getSession();
			String token = null;
			if ( session != null ) {
				token = (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
			}

			if ( token != null ) {
				parameters.put(Constants.TOKEN_KEY, token);
			}
		}

		String result = null;
		try {
			result = WebappUtil.computeURL(action, forward, href, anchor, parameters, request, response, true, true, addLocaleSuffix.booleanValue());
		} catch ( MalformedURLException e ) {
			TagUtils.getInstance().saveException(pageContext, e);
			throw new JspTagException(e);
		}

		// perform redirect
		response.sendRedirect(result);
	}

	/**
	 * @see com.blandware.atleap.webapp.taglib.core.ParamParent#addParameter(String, Object)
	 */
	public void addParameter(String name, Object value) {
		parameters.put(name, RequestUtil.mergeValues(parameters.get(name), value));
	}

}
